{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 特征图的处理\n",
    "从特征图还原"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):  \n",
    "    \"\"\"  \n",
    "    将卷积后的特征图转换回原始图像大小的函数。  \n",
    "\n",
    "    Parameters  \n",
    "    ----------  \n",
    "    col :   \n",
    "        卷积后的特征图。  \n",
    "    input_shape :   \n",
    "        输入数据的形状，例如(10, 1, 28, 28)，其中10是批量大小，1是通道数，28是高和宽。  \n",
    "    filter_h :   \n",
    "        卷积核的高度。  \n",
    "    filter_w :   \n",
    "        卷积核的宽度。  \n",
    "    stride :   \n",
    "        步长，默认为1。  \n",
    "    pad :   \n",
    "        填充大小，默认为0。  \n",
    "\n",
    "    Returns  \n",
    "    -------  \n",
    "    img :   \n",
    "        返回转换后的图像。  \n",
    "    \"\"\"  \n",
    "    # 从输入形状中获取批量大小、通道数、高度和宽度  \n",
    "    N, C, H, W = input_shape  \n",
    "    # 计算卷积后的高度和宽度  \n",
    "    out_h = (H + 2*pad - filter_h)//stride + 1  \n",
    "    out_w = (W + 2*pad - filter_w)//stride + 1  \n",
    "    # 调整卷积后的特征图的形状，以便进行正确的广播  \n",
    "    col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2)  \n",
    "\n",
    "    # 创建一个全零的数组，用于保存转换后的图像  \n",
    "    img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1))  \n",
    "    # 遍历卷积核的每个元素  \n",
    "    for y in range(filter_h):  \n",
    "        # 计算当前元素在特征图上的结束位置  \n",
    "        y_max = y + stride*out_h  \n",
    "        for x in range(filter_w):  \n",
    "            # 计算当前元素在特征图上的结束位置  \n",
    "            x_max = x + stride*out_w  \n",
    "            # 在对应的位置上加上卷积后的特征图的值  \n",
    "            img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]  \n",
    "\n",
    "    # 返回转换后的图像，只保留原始图像范围内的部分  \n",
    "    return img[:, :, pad:H + pad, pad:W + pad]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "图片一维化方便卷积，主要目的是将输入图像转换为一种列向量形式，这通常在卷积神经网络中用于计算卷积。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def im2col(input_data, filter_h, filter_w, stride=1, pad=0):  \n",
    "    \"\"\"  \n",
    "    将输入图像转换为列向量形式。  \n",
    "\n",
    "    Parameters  \n",
    "    ----------  \n",
    "    input_data : 由(数据量, 通道, 高, 长)的4维数组构成的输入数据  \n",
    "    filter_h : 滤波器的高  \n",
    "    filter_w : 滤波器的长  \n",
    "    stride : 步幅，默认为1  \n",
    "    pad : 填充，默认为0  \n",
    "\n",
    "    Returns  \n",
    "    -------  \n",
    "    col : 2维数组，包含转换后的列向量  \n",
    "    \"\"\"  \n",
    "    N, C, H, W = input_data.shape  # 获取输入数据的维度信息  \n",
    "    out_h = (H + 2*pad - filter_h)//stride + 1  # 计算卷积后的高度  \n",
    "    out_w = (W + 2*pad - filter_w)//stride + 1  # 计算卷积后的宽度  \n",
    "\n",
    "    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')  # 对输入数据进行填充  \n",
    "    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))  # 初始化一个用于保存结果的数组  \n",
    "\n",
    "    for y in range(filter_h):  # 遍历滤波器的每一行  \n",
    "        y_max = y + stride*out_h  # 计算当前行在输出特征图上的结束位置  \n",
    "        for x in range(filter_w):  # 遍历滤波器的每一列  \n",
    "            x_max = x + stride*out_w  # 计算当前列在输出特征图上的结束位置  \n",
    "            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]  # 将对应位置的输入数据复制到结果数组中  \n",
    "\n",
    "    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)  # 将结果数组转换为列向量形式  \n",
    "    return col  # 返回转换后的列向量"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
